<?php
// +----------------------------------------------------------------------
// | [KyPHP System] Copyright (c) 2020 http://www.kuryun.com/
// +----------------------------------------------------------------------
// | [KyPHP] 并不是自由软件,你可免费使用,未经许可不能去掉KyPHP相关版权
// +----------------------------------------------------------------------
// | Author: fudaoji <fdj@kuryun.cn>
// +----------------------------------------------------------------------

/**
 * Created by PhpStorm.
 * Script Name: Mp.php
 * Create: 2020/5/22 下午11:15
 * Description: 公众号管理
 * Author: fudaoji<fdj@kuryun.cn>
 */

namespace app\system\controller;

use app\admin\controller\FormBuilder;
use app\common\model\AdminStore;
use ky\MiniPlatform\Request\ComponentModifyWxaServerDomain;
use ky\MiniPlatform\RequestClient;
use think\Db;
use think\facade\Log;

class Mp extends Base
{
    /**
     * @var \app\common\model\Mp $mpM
     */
    private $mpM;
    /**
     * @var \think\Model
     */
    private $storeM;
    private $mpInfo;
    public function initialize()
    {
        parent::initialize(); // TODO: Change the autogenerated stub
        $this->mpM = model('mp');
        $this->storeM = model('adminStore');
        if(isset(input()['mid'])){
            $this->mpInfo = $this->mpM->getOne(input('mid', 0, 'intval'));
            if(empty($this->mpInfo)){
                $this->error('公众号不存在');
            }
        }
    }

    /**
     * 上传开放平台校验文件
     * Author: fudaoji<fdj@kuryun.cn>
     */
    public function verifyFilePost(){
        if(request()->isPost()){
            try {
                // 获取表单上传文件 例如上传了001.jpg
                $file = request()->file('file');
                // 移动到服务器的上传目录 并且使用原文件名
                $res = $file->validate(['size'=>2000, 'ext'=>'txt'])->move(ROOT_PATH,'');
                if(! $res){
                    $this->error($file->getError());
                }
                //保存
                $setting = model('setting')->getOneByMap(['name' => 'weixin']);
                $weixin_setting = json_decode($setting['value'], true);
                $weixin_setting['platform']['verify_file'] = '/'.$res->getFilename();
                model('setting')->updateOne([
                    'id' => $setting['id'],
                    'value' => json_encode($weixin_setting)
                ]);
                model('setting')->settings(true);  //refresh cache
            }catch (\Exception $e){
                $this->error('系统错误:' . $e->getMessage());
                $res = false;
            }
            if($res){
                $this->success('上传成功', '', ['src' => '/' . $res->getFilename()]);
            }
        }
    }

    /**
     * 获取开放平台正式版服务器域名
     * @return string
     * @throws \Exception
     * Author: fudaoji<fdj@kuryun.cn>
     */
    private function getWxaServerDomain(){
        $client = new RequestClient();
        $access_token = controller('mp/mp', 'event')->getOpenPlatform()->access_token->getToken()['component_access_token'];
        $request = new ComponentModifyWxaServerDomain();
        $request->setAction('get');
        $response = $client->execute($request, $access_token);
        if(!empty($response['published_wxa_server_domain'])){
            return $response['published_wxa_server_domain'];
        }
        return '';
    }

    /**
     * 设置开放平台正式版服务器域名
     * @return string
     * @throws \Exception
     * Author: fudaoji<fdj@kuryun.cn>
     */
    private function setWxaServerDomain($params = []){
        $client = new RequestClient();
        $access_token = controller('mp/mp', 'event')->getOpenPlatform()->access_token->getToken()['component_access_token'];
        $request = new ComponentModifyWxaServerDomain();
        $request->setAction('set');
        $request->setIsModifyPublishedTogether(true);
        $request->setWxaServerDomain($params['wxa_server_domain']);
        $response = $client->execute($request, $access_token);
        if(intval($response['errcode']) !== 0) {
            $this->error($response['errmsg']);
        }
    }

    /**
     * 开放平台信息
     * @return mixed
     * Author: fudaoji<fdj@kuryun.cn>
     * @throws \Exception
     */
    public function platform(){
        $setting = model('setting')->getOneByMap(['name' => 'weixin']);
        $platform = [
            'appid' => '',
            'appsecret' => '',
            'token'  => get_rand_char(32),
            'aes_key' => get_rand_char(43),
            'verify_file' => '',
            'wxa_server_domain' => $this->getWxaServerDomain(),
            'wxa_jump_h5_domain' => ''
        ];
        if(empty($setting)){
            $weixin_setting = ['platform' => $platform];
            $setting = model('setting')->addOne([
                'name' => 'weixin',
                'title' => '微信',
                'value' => json_encode($weixin_setting)
            ]);
        }else{
            $weixin_setting = json_decode($setting['value'], true);
            if(empty($weixin_setting['platform'])){
                $weixin_setting['platform'] = $platform;
                model('setting')->updateOne([
                    'id' => $setting['id'],
                    'value' => json_encode($weixin_setting)
                ]);
            }else{
                $platform = array_merge($platform, $weixin_setting['platform']);
            }
        }

        if(request()->isPost()){
            $post_data = input('post.');
            $data = array_merge($platform, $post_data);
            $weixin_setting['platform'] = $data;
            $res = model('setting')->updateOne([
                'id' => $setting['id'],
                'value' => json_encode($weixin_setting, JSON_UNESCAPED_UNICODE)
            ]);
            if($res){
                if(!empty($post_data['wxa_server_domain'])){
                    $this->setWxaServerDomain($post_data);
                }
                model('setting')->settings(true);  //refresh cache
                $this->success('保存成功');
            }else{
                $this->error('保存失败，请刷新重试');
            }
        }

        $this->assign['platform'] = $platform;
        return $this->show();
    }

    /**
     * 编辑手动接入的公众号
     * @return mixed
     * @throws \think\Exception
     * @author: fudaoji<fdj@kuryun.cn>
     */
    public function edit(){
        if(request()->isPost()){
            $post_data = input('post.');

            $res = $this->validate($post_data,'Mp.edit');
            if($res !== true){
                $this->error($res, '', ['token' => request()->token()]);
            }
            if($this->mpM->updateOne($post_data)){
                $this->success('编辑成功', url('info', ['mid' => $this->mpInfo['id']]));
            }else{
                $this->error('编辑失败，请刷新重试', '', ['token' => request()->token()]);
            }
        }
        $builder = new FormBuilder();
        $builder->addFormItem('id', 'hidden', 'id', 'id')
            ->addFormItem('nick_name', 'text', '公众号昵称', '不超过30字', [], 'required maxlength=30')
            ->addFormItem('service_type_info', 'radio', '类型', '类型', model('mp')->serviceTypes(), 'required')
            ->addFormItem('verify_type_info', 'select', '认证', '认证', model('mp')->verifyTypes(), 'required')
            ->addFormItem('appid', 'text', 'APPID', '公众号appID', [], 'required')
            ->addFormItem('appsecret', 'text', 'APPSecret', '公众号APPSecret', [], 'required')
            ->addFormItem('refresh_token', 'text', 'Token令牌', '请设置复杂一些', [], 'required minlength=4')
            ->addFormItem('user_name', 'text', '原始ID', '原始ID', [], 'required')
            ->addFormItem('alias', 'text', '微信号', '微信号')
            ->addFormItem('head_img', 'picture_url', '头像', '头像')
            ->addFormItem('qrcode_url', 'picture_url', '二维码', '关注二维码')
            ->addFormItem('verify_file', 'file_to_root', '校验文件', '校验文件')
            ->setFormData($this->mpInfo);
        return $builder->show();
    }

    /**
     * 管理设置
     * @return mixed
     * Author: fudaoji<fdj@kuryun.cn>
     */
    public function info(){
        $this->mpInfo['url'] = request()->domain() . url('mp/api/index', ['appid' => $this->mpInfo['appid']]);
        $assign = ['mp' => $this->mpInfo];
        return $this->show($assign);
    }

    /**
     * 公众号列表
     * @return mixed
     * Author: fudaoji<fdj@kuryun.cn>
     * @throws \think\exception\DbException
     */
    public function index()
    {
        $mp_list = $this->mpM->page($this->pageSize, ['uid' => $this->adminId], ['update_time' => 'desc'],true, 1);
        $page = $mp_list->render();
        foreach ($mp_list as $key => $v) {
            $v['type'] = controller('common/mp', 'event')->getTypeDesc($v);
            $mp_list[$key] = $v;
        }
        return $this->show(['mp_list' => $mp_list, 'page' => $page]);
    }

    /**
     * 选择添加方式
     * @return mixed
     * @author: fudaoji<fdj@kuryun.cn>
     */
    public function choose(){
        $this->checkCanAdd();
        return $this->show();
    }

    /**
     * 判断是否可以继续添加公众号
     * @author: fudaoji<fdj@kuryun.cn>
     */
    protected function checkCanAdd(){
        $res = controller('common/adminGroup', 'event')->canAddStore([
            'admin_info' => $this->adminInfo,
            'type' => 'mp'
        ]);
        if($res === false){
            $this->error('您当前添加的公众号数量已达上限，请升级会员');
        }
    }

    /**
     * 手动添加公众号
     * @return mixed
     * @throws \think\Exception
     * @author: fudaoji<fdj@kuryun.cn>
     */
    public function add(){
        if(request()->isPost()){
            $post_data = input('post.');
            Db::startTrans();
            try{
                $store = $this->storeM->addOne(['uid' => $this->adminId, 'type' => AdminStore::MP]);
                $res = $this->validate($post_data,'Mp.add');
                if($res !== true){
                    $this->error($res, '', ['token' => request()->token()]);
                }
                $post_data['refresh_token'] = get_rand_char(32);
                $post_data['encodingaeskey'] = get_rand_char(43);
                $post_data['uid'] = $this->adminId;
                $post_data['id'] = $store['id'];
                $res = $this->mpM->addOne($post_data);
                Db::commit();
            }catch (\Exception $e){
                Log::write($e->getMessage());
                $res = false;
                Db::rollback();
            }
            if($res){
                $this->success('添加成功', url('index'));
            }else{
                $this->error('添加失败，请刷新重试', '', ['token' => request()->token()]);
            }
        }
        $builder = new FormBuilder();
        $builder->addFormItem('nick_name', 'text', '公众号昵称', '不超过30字', [], 'required maxlength=30')
            ->addFormItem('service_type_info', 'radio', '类型', '类型', model('mp')->serviceTypes(), 'required')
            ->addFormItem('verify_type_info', 'select', '认证', '认证', model('mp')->verifyTypes(), 'required')
            ->addFormItem('appid', 'text', 'APPID', '公众号appID', [], 'required')
            ->addFormItem('appsecret', 'text', 'APPSecret', '公众号APPSecret', [], 'required')
            ->addFormItem('user_name', 'text', '原始ID', '原始ID', [], 'required')
            ->addFormItem('alias', 'text', '微信号', '微信号')
            ->addFormItem('head_img', 'picture_url', '头像', '头像')
            ->addFormItem('qrcode_url', 'picture_url', '二维码', '关注二维码')
            ->addFormItem('verify_file', 'file_to_root', '校验文件', '校验文件');
        return $builder->show();
    }

    /**
     * 删除
     * Author: fudaoji<fdj@kuryun.cn>
     */
    public function delete(){
        if (request()->isPost()) {
            $id = input('id');
            $this->mpM->delOne($id);
            $this->success('删除成功');
        }
    }

    /**
     * 设置状态
     * Author: fudaoji<fdj@kuryun.cn>
     */
    public function setStatus(){
        if (request()->isPost()) {
            Db::startTrans();
            try{
                $this->mpM->updateOne([
                    'id' => $this->mpInfo['id'],
                    'status' => abs($this->mpInfo['status'] - 1)
                ]);
                $this->storeM->updateOne([
                    'id' => $this->mpInfo['id'],
                    'status' => abs($this->mpInfo['status'] - 1)
                ]);
                Db::commit();
                $res = true;
            }catch (\Exception $e){
                Log::write(json_encode($e->getMessage()));
                Db::rollback();
                $res = false;
            }
            if($res){
                $this->success('操作成功');
            }else{
                $this->error('操作失败，请刷新重试');
            }
        }
    }
}